<script>
import SelfFormTemp from '../form/Index.vue'
import SelfTableItem from './SelfTableItem.vue'

export default {
  name: 'FilterTableTemplate',
  components: { SelfFormTemp, SelfTableItem },
  props: {
    config: {
      type: Object,
      default: () => ({
        key: 'page',
        filters: [],
        tableSettings: {
          api: undefined,
          params: {},
          columns: [],
          formmat: undefined,
          showPage: true,
          field: {}
        }
      })
    },
    selfKey: {
      type: String,
      default: 'work'
    }
  },
  data() {
    return {
      filter: {},
      loading: false,
      tableData: [],
      pageSizes: [10, 20, 30, 40],
      page: {
        page: 1,
        limit: 10
      },
      total: 0,
      tableWidth: '',
      tableField: {
        total: 'count',
        list: 'data',
        page: 'page',
        limit: 'limit'
      }
    }
  },
  computed: {
    _tableField() {
      if (this.config.tableSettings.field) {
        return { ...this.tableField, ...this.config.tableSettings.field }
      }
      return this.tableField
    }
  },
  watch: {
    config: {
      handler(newVal, oldVal) {
        // 判断是否是非filter选项的变化
        if (this.hasConfigChanged(newVal, oldVal)) {
          this.filter = {}
          this.tableData = []
          this.page = {
            page: 1,
            limit: 10
          }
          this.total = 0
          this.handleGetData()
        }
      },
      deep: true,
      immediate: true
    }
  },
  // 解决表头变动，数据下掉问题
  // 使用v-if并不会重新渲染表格，并可能存在表头乱飞现象，使用element的dolayout解决
  beforeUpdate() {
    this.$nextTick(() => { // 在数据加载完，重新渲染表格
      this.$refs.tableRef && this.$refs.tableRef.doLayout()
    })
  },
  mounted() {
    //   获取ref content的宽度
    this.tableWidth = this.$refs.table ? this.$refs.table.clientWidth : 'auto'
  },
  methods: {
    hasConfigChanged(newConfig, oldConfig) {
      if (!oldConfig) return true

      // 克隆配置并排除filter的options属性
      const clone = (config) => {
        const copied = JSON.parse(JSON.stringify(config))
        if (copied.filters) {
          copied.filters.forEach(filter => delete filter.options)
        }
        return copied
      }

      const newClone = clone(newConfig)
      const oldClone = clone(oldConfig)

      return JSON.stringify(newClone) !== JSON.stringify(oldClone)
    },
    setLoading(row, val) {
      this.tableData.forEach(item => {
        if (item.id === row.id) {
          item.loading = val
        }
      })
    },
    async handleGetData() {
      this.tableData = []
      if (this.config.tableSettings) {
        if (this.config.tableSettings.api) {
          let propParams = this.config.tableSettings.params
          if (typeof this.config.tableSettings.params === 'function') {
            propParams = this.config.tableSettings.params(this.filter)
          }
          let params = { ...this.filter, ...propParams }
          if (!('showPage' in this.config.tableSettings) || (this.config.tableSettings.showPage)) {
            const page = {
              [this._tableField['page']]: this.page.page,
              [this._tableField['limit']]: this.page.limit
            }
            params = { ...params, ...page }
          }
          try {
            this.loading = true
            const res = await this.config.tableSettings.api(params)
            if (res.code === 200 && res.data) {
              const dataField = this._tableField['list']
              if (this.config.tableSettings.formmat) {
                this.tableData = this.config.tableSettings.formmat(res)
              } else {
                if (!res.data[dataField]) {
                  this.$message.error('数据格式错误')
                  return
                }
                this.tableData = res.data[dataField]
                const totalField = this._tableField['total']
                if (res.data[totalField]) {
                  this.total = res.data[totalField]
                }
              }
              this.$emit('get-data', res)
            } else {
              this.$message.error(res.msg)
            }
          } catch (err) {
            console.log(err)
          } finally {
            this.loading = false
          }
        } else {
          this.tableData = this.config.tableSettings.data
        }
      }
    },
    handleReset() {
      this.$refs.filterWrapRef.$refs.filterRef.resetFields()
      this.handleGetData()
    },
    handleSizeChange(val) {
      this.page.limit = val
      this.handleGetData()
    },
    handleCurrentChange(val) {
      this.page.page = val
      this.handleGetData()
    },
    getWidth(width) {
      if (!width) return ''
      if (typeof width === 'string' && width.indexOf('%') !== -1) {
        width = width.replace('%', '')
        return this.tableWidth * width / 100 + 'px'
      }
      return width
    },
    handleSelectionChange(val) {
      this.$emit('selection-change', val)
    },
    sortChange({ column, prop, order }) {
      this.$emit('sort-change', { column, prop, order })
    }
  }
}
</script>

<template>
  <div id="statistics-template" ref="filterListRef" v-loading="loading">
    <div v-if="(config.filters && config.filters.length) || $slots.topActions" :class="['filter', {'block': !config.filters || !config.filters.length}]">
      <self-form-temp
        v-if="config.filters && config.filters.length"
        ref="filterWrapRef"
        :form-data.sync="filter"
        :inline="true"
        :filters="config.filters"
        :self-key="selfKey"
      >
        <el-form-item style="margin-left: 10px;">
          <el-button type="primary" @click="handleGetData">查询</el-button>
          <el-button @click="handleReset">重置</el-button>
        </el-form-item>
      </self-form-temp>
      <div v-if="$slots.topActions" class="actions">
        <slot name="topActions" />
      </div>
    </div>
    <div v-if="config.tableSettings" ref="table" class="table">
      <el-table
        ref="tableRef"
        :data="tableData"
        :height="config.tableSettings.height || '100%'"
        style="width: 100%"
        @selection-change="handleSelectionChange"
        @sort-change="sortChange"
      >
        <el-table-column v-if="config.tableSettings.selection" type="selection" width="55" />
        <el-table-column v-if="config.tableSettings.index" type="index" label="序号" width="80" :sortable="true" />
        <el-table-column
          v-for="(item, index) in config.tableSettings.columns"
          :key="index + '_' + Math.random()"
          :label="item.label"
          :prop="item.prop"
          :width="getWidth(item.width)"
          :min-width="getWidth(item.minWidth)"
          :align="item.align"
          :sortable="item.sortable"
          :formatter="item.formatter"
          :show-overflow-tooltip="true"
          :fixed="item.fixed"
        >
          <template v-if="item.children && item.children.length">
            <self-table-item
              v-for="(child, childIndex) in item.children"
              :key="childIndex + '_c_' + Math.random()"
              :column="child"
              :config-key="config.key"
              :min-width="child.minWidth"
              :table-width="tableWidth"
            >
              <template v-if="child.isSlot" :slot="config.key + '_' + child.prop" slot-scope="{row}">
                {{ row }}
                <slot :name="config.key + '_' + child.prop" :row="row[child.prop]" />
              </template>
            </self-table-item>
          </template>
          <template slot-scope="{row}">
            <slot v-if="item.isSlot" :name="config.key + '_' + item.prop" :row="row" />
            <div v-else-if="item.type === 'img'">
              <el-image v-if="item.settings" style="width: 100px; height: 100px" :src="item.settings.baseUrl ? (item.settings.baseUrl + row[item.prop]) : row[item.prop]" :fit="'fit'" :preview-src-list="[item.settings.baseUrl ? (item.settings.baseUrl + row[item.prop]) : row[item.prop]]" />
            </div>
            <span v-else>{{ row[item.prop] }}</span>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <div
      v-if="config.tableSettings && ('showPage' in config.tableSettings ? config.tableSettings.showPage : true)"
      class="page"
    >
      <el-pagination
        :current-page="page.page"
        :page-sizes="pageSizes"
        :page-size="page.limit"
        layout="total, sizes, prev, pager, next, jumper"
        background
        :total="total"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>
  </div>
</template>

<style scoped lang="scss">
  #statistics-template {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 300px;

    .filter {
      display: flex;
      align-items: center;
      justify-content: space-between;
      border-bottom: 1px solid #e8e8e8;
      padding: 0 20px;
      flex-wrap: wrap;
      flex-shrink: 0;

      ::v-deep .el-form--inline .el-form-item {
        margin-right: 15px;
      }

      &.block {
        display: block;
      }

      .actions{
        margin-bottom: 22px;
      }
    }

    .table {
      margin-top: 20px;
      flex: 1;
      overflow-y: auto;
    }

    .page {
      margin-top: 20px;
      text-align: center;
    }
  }
</style>
